package core.dao.impl;

import java.util.List;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.hibernate.HibernateException;
import org.hibernate.Session;

import java.io.Serializable;
import java.sql.SQLException;

import org.hibernate.Query;
import org.hibernate.transform.Transformers;

import core.dao.BaseDao;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import util.Sessions;
import util.Tool;

public class BaseDaoImpl<T extends Serializable> extends HibernateDaoSupport implements BaseDao<T>{
	protected Class<T> persistType;
	//private static final Logger log = LoggerFactory.getLogger(BaseDaoImpl.class);
	private static final Logger log=LoggerFactory.getLogger("INFO");
	
	public BaseDaoImpl(Class<T> persistType) {
		this.persistType = persistType;
	}
	
	@Override
	public T save(T entity) {
		getHibernateTemplate().saveOrUpdate(entity);
		return entity;
	}
	
	@Override
	public T saveOrUpdate(T entity) {
		getHibernateTemplate().saveOrUpdate(entity);
		return entity;
	}

	@Override
	public T merge(T entity) {
		getHibernateTemplate().merge(entity);
		return entity;
	}

	@Override
	public void update(T entity){
		getHibernateTemplate().update(entity);   
	}
	
	@Override
	public void delete(T entity){
		getHibernateTemplate().delete(entity); 
	}
	
	@Override
	public void evict(T entity) {
		getHibernateTemplate().evict(entity);
	}
	
    @Override
	public List<T> findAll() {
/*		try {
			String queryString =persistType.getName();
			log.info("findAll->"+queryString);
			return getHibernateTemplate().find(queryString);
		} catch (RuntimeException re) {
			throw re;
		}*/
    	return findModel("ALL");
	}
	
    @Override
    public T findByOne(String hql){
    	StringBuffer queryString=new StringBuffer(persistType.getName()).append(" where ").append(hql);
		//String queryString = persistType.getName()+" where "+hql;
		List<T> list=findQuery("",queryString.toString(),1);
		return list==null?null:list.get(0);
    }
	
    @Override
    public T findOne(String name,String value){
    	StringBuffer queryString=new StringBuffer(name).append("='").append(value).append("'");
		//String queryString =name+"='"+value+"'";
		log.info("findOne->"+queryString);
		return findByOne(queryString.toString());
    }

    @Override
    public T findOne(String name,int value){
    	StringBuffer queryString=new StringBuffer(name).append("=").append(value);
		//String queryString =name+"="+value;
		log.info("findOne->"+queryString);
		return findByOne(queryString.toString());
    }

    @Override
    public T findOne(String name,long value){
    	StringBuffer queryString=new StringBuffer(name).append("=").append(value);
		//String queryString =name+"="+value;
		log.info("findOne->"+queryString);
		return findByOne(queryString.toString());
    }
    
	@Override
	public List<T> findList(String name,String value){
		StringBuffer queryString=new StringBuffer(persistType.getName()).append(" where ").append(name)
				.append("='").append(value).append("'");
		//String queryString = persistType.getName()+" where "+name+"='"+value+"'";
		log.info("findByList->"+queryString);
     	//List<T> list=(List<T>)getHibernateTemplate().find(queryString);
		return findQuery("",queryString.toString());
	}
    
	@Override
	public List<T> findList(String name,int value){
		//String queryString = persistType.getName()+" where "+name+"="+value;
		StringBuffer queryString=new StringBuffer(persistType.getName()).append(" where ").append(name)
				.append("=").append(value);
		log.info("findByList->"+queryString);
		//List<T> list=(List<T>) getHibernateTemplate().find(queryString);
		//return list.isEmpty()?null:list;
		return findQuery("",queryString.toString());
	}
    
	@Override
	public T getId(String id) {
		return (T) getHibernateTemplate().get(persistType, id);
	}
	

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public int countQuery(String hql) {
		StringBuffer ccounthql=new StringBuffer("select count(*) from ").append(hql);
		final String counthql=ccounthql.toString();
		//final String counthql = "select count(*) from "+hql;
		Long count = (Long)getHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session session) throws HibernateException{
				Query query = session.createQuery(counthql).setMaxResults(1);
				log.info("countQuery->"+query.uniqueResult());
				return query.uniqueResult();
			}
		});
		return count.intValue();
	}
	
	@Override
	public int countSqlQuery(String from) {
		StringBuffer ccounthql=new StringBuffer("select count(*) from ").append(from);
		final String counthql=ccounthql.toString();
		return countFullSqlQuery(counthql);
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public int countFullSqlQuery(final String sql) {
		Integer  count = (Integer)getHibernateTemplate().execute(new HibernateCallback(){
			public Object doInHibernate(Session session) throws HibernateException{
				Query query =session.createSQLQuery(sql);
				log.info("countSqlQuery->"+query.uniqueResult());
				return ((Number)query.uniqueResult()).intValue();  
			}
		});
		return count;
	}
	
	@Override
	public int countModel(String where) {
		StringBuffer queryhql=new StringBuffer(persistType.getName());
		if(!where.equals("ALL")) queryhql.append(" as a where ").append(where);
    	//String queryhql=persistType.getName();
    	//if(where!="ALL") queryhql+=" as a where "+ where;
		return countQuery(queryhql.toString());
	}
    
    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
	public List<T> findQuery(final String select,final String from,final int pageSize){
        return (List<T>) getHibernateTemplate().execute(new HibernateCallback(){
            public Object doInHibernate(Session session)
                    throws HibernateException, SQLException {
            	StringBuffer temp=new StringBuffer();            	
            	String hql=select.equals("")?
            			temp.append(" from ").append(from).toString():
            			temp.append("select ").append(select).append(" from ").append(from).toString();
            	//String hql=select.equals("")?" from "+from:"select "+select+" from "+from;
                Query query=session.createQuery(hql);
    			if(pageSize>1){
    				int curPage=Tool.getCurPage();
    				query.setFirstResult((curPage-1)*pageSize).setMaxResults(pageSize).setFetchSize(pageSize);
    				Sessions.set("pagetotal",(int)Math.ceil((double)countQuery(from)/(double)pageSize));    				
    			}else if(pageSize==1){
    				query.setFirstResult(0).setMaxResults(1).setFetchSize(1);
    			}
    			log.info("findPage->"+hql);
    			List<T> list=query.list();    
                return (list==null||list.isEmpty())?null:list;     
            }
        });
    }
    
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public List<T> findSqlQuery(final String select,final String from,final int pageSize){
        return (List<T>) getHibernateTemplate().execute(new HibernateCallback(){
            public Object doInHibernate(Session session)
                    throws HibernateException, SQLException {
            	StringBuffer temp=new StringBuffer(); 
            	String hql=select.equals("")?
            			temp.append(" from ").append(from).toString():
            			temp.append("select ").append(select).append(" from ").append(from).toString();
            	//String hql=select.equals("")?" from "+from:"select "+select+" from "+from;
                Query query=session.createSQLQuery(hql);
                query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
    			if(pageSize>1){
    				int curPage=Tool.getCurPage();
    				query.setFirstResult((curPage-1)*pageSize).setMaxResults(pageSize).setFetchSize(pageSize);
    				Sessions.set("pagetotal",(int)Math.ceil((double)countSqlQuery(from)/(double)pageSize));    				
    			}else if(pageSize==1){
    				query.setFirstResult(0).setMaxResults(1).setFetchSize(1);
    			}
    			log.info("findPage->"+hql);
    			List<T> list=query.list();    			
                return (list.isEmpty()||list==null)?null:list;     
            }
        });
    }
    
    @Override
	public List<T> findQuery(final String select,final String hql){
        return findQuery(select,hql,0);
    }
    
    @Override
	public List<T> findModel(final String hql,final int pageSize){
		StringBuffer queryhql=new StringBuffer(persistType.getName());
		if(!hql.equals("ALL")) queryhql.append(" as a where ").append(hql);
    	//String queryhql=persistType.getName();
    	//if(hql!="ALL") queryhql+=" where "+hql;
    	return findQuery("",queryhql.toString(),pageSize);
    }
    
    @Override
	public List<T> findModel(final String hql){
    	return findModel(hql,0);
    }
 
}
